// Package lookup
// Copyright 2016-2023 chad.wang<chad.wang@icloudsky.com>. All rights reserved.
package lookup

import (
	"context"
	"encoding/json"
	"gitee.com/marcellos/wow-updte-ip/internal/dao"
	"gitee.com/marcellos/wow-updte-ip/internal/model"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/gclient"
	"github.com/gogf/gf/v2/os/gctx"
	"github.com/marcellowy/go-common/gogf/vlog"
	"io"
	"time"
)

type Ip struct {
	LastIp string
}

func NewIp() *Ip {
	return &Ip{}
}

func (*Ip) Get(ctx context.Context) (list []string, err error) {
	client := gclient.New()
	var response *gclient.Response
	response, err = client.Get(ctx, g.Config().MustGet(ctx, "getNetworkInterfaceIpUrl").String())
	if err != nil {
		return
	}
	defer response.Body.Close()
	var b []byte
	if b, err = io.ReadAll(response.Body); err != nil {
		return
	}

	type responseBody struct {
		Ip string `json:"ip"`
	}

	var res = responseBody{}
	if err = json.Unmarshal(b, &res); err != nil {
		return
	}
	if len(res.Ip) > 0 {
		list = append(list, res.Ip)
	}
	return
}

// updateIp biz logic
func (i *Ip) updateIp(ctx context.Context, timeout time.Duration) {
	// cxx := gctx.New()
	cxx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	go func(ctx context.Context) {

		list, err := i.Get(ctx)
		if err != nil {
			vlog.Error(ctx, "get ip error: ", err)
			return
		}
		if len(list) == 0 {
			vlog.Warning(ctx, "list is empty")
			return
		}
		if list[0] == i.LastIp {
			vlog.Info(ctx, "current ip same last ip")
			return
		}
		// update database
		err = dao.Db.Where("id=1").Updates(&model.RealmList{
			Id:      1,
			Address: list[0],
		}).Error

		if err != nil {
			vlog.Error(ctx, err)
			return
		}

		vlog.Debug(ctx, "update realmList.address successfully")
		i.LastIp = list[0]
	}(ctx)

	select {
	case <-cxx.Done():
		// successfully
		return
	case <-time.After(timeout + time.Second):
		// timeout
		vlog.Warning(ctx, "timeout")
		return
	}
}

func (i *Ip) Run(ctx context.Context) {

	var (
		timeout  = 3 * time.Second
		interval = 10 * time.Second
	)

	i.updateIp(ctx, timeout)

	for {
		select {
		case <-time.After(interval):
			i.updateIp(gctx.New(), timeout)
		}
	}
}
